package gateway

import (
	"fmt"
	"net/http"
	"strings"

	previewer "gitee.com/zh-jn/harmonica-previewer-online/previewer/harmonica/v1"
	managercli "gitee.com/zh-jn/harmonica-previewer-online/previewer/harmonica/v1/manager/client"
)

func NewPreviewerGateway(
	previewerPoolNamespace string,
	previewerPort int,
	managerAddr string,
	managerPort int,
	sessionKey string,
	wsTimeout int,
) *PreviewerGateway {
	return &PreviewerGateway{
		previewerPoolNamespace: previewerPoolNamespace,
		previewerPort:          previewerPort,
		managerCli: managercli.NewManagerClient(managercli.ClientConfig{
			Addr: managerAddr,
			Port: managerPort,
		}),
		sessionKey: sessionKey,
		wsTimeout:  wsTimeout,
	}
}

type PreviewerGateway struct {
	previewerPoolNamespace string
	previewerPort          int
	managerCli             *managercli.ManagerClient
	sessionKey             string
	wsTimeout              int
}

func (p *PreviewerGateway) ServeHTTP(w http.ResponseWriter, r *http.Request) {
	hostname := r.Host
	previewerId, sessionId := p.parseHostName(hostname)
	if previewerId == "" {
		w.WriteHeader(http.StatusBadGateway)
		w.Write([]byte(fmt.Sprintf("invalid hostname(previewer) %v", hostname)))
		return
	}
	if ok, err := checkSessionId(p.sessionKey, sessionId); !ok {
		w.WriteHeader(http.StatusBadGateway)
		w.Write([]byte(fmt.Sprintf("invalid hostname(session) err, %v, %v", hostname, err)))
		return
	}
	if err := p.managerCli.CheckBinding(sessionId, previewerId); err != nil {
		w.WriteHeader(http.StatusForbidden)
		w.Write([]byte(fmt.Sprintf("check binding failed, %v", err)))
		return
	}
	previewer, err := previewer.NewHarmonicaPreviewer(previewerId, fmt.Sprintf("%v.%v", previewerId, p.previewerPoolNamespace), p.previewerPort, p.wsTimeout)
	if err != nil {
		w.WriteHeader(http.StatusBadGateway)
		w.Write([]byte(fmt.Sprintf("new previewer err, %v", err)))
		return
	}
	previewer.ServeHTTP(w, r)
}

func (p *PreviewerGateway) parseHostName(hostname string) (previewerId, sessionId string) {
	comp := strings.Split(hostname, ".")
	if len(comp) == 0 {
		return "", ""
	}
	ret := comp[0]
	if !strings.HasPrefix(ret, "previewer-") {
		return "", ""
	}

	comp = strings.Split(ret, "-")
	if len(comp) != 3 {
		return "", ""
	}

	return strings.Join(comp[:2], "-"), comp[2]
}
